﻿using PmSoft.FormSchema.Attributes;
using System.Collections.Concurrent;
using System.ComponentModel.DataAnnotations;
using System.Reflection;

namespace PmSoft.FormSchema;

/// <summary>
/// 反射缓存管理器 - 负责缓存反射相关的属性和特性
/// </summary>
public static class ReflectionCacheManager
{
	// 缓存类型属性信息的字典
	private static readonly ConcurrentDictionary<Type, PropertyInfo[]> PropertyCache = new();

	// 缓存属性特性的字典
	private static readonly ConcurrentDictionary<PropertyInfo, Dictionary<Type, Attribute>> AttributeCache = new();

	// 缓存枚举选项的字典
	private static readonly ConcurrentDictionary<Type, List<object>> EnumOptionsCache = new();

	// 缓存根据 FormNameAttribute 查找的类型的字典（不区分大小写）
	private static readonly ConcurrentDictionary<(string FormName, string AssemblyName), Type?> FormNameTypeCache =
		new();

	/// <summary>
	/// 获取缓存的属性信息，若无则反射并缓存
	/// </summary>
	public static PropertyInfo[] GetCachedProperties(Type type) =>
		PropertyCache.GetOrAdd(type, t => t.GetProperties());

	/// <summary>
	/// 获取缓存的属性特性，若无则反射并缓存，支持基类匹配
	/// </summary>
	/// <typeparam name="T">要查找的特性类型</typeparam>
	/// <param name="prop">属性信息</param>
	/// <returns>匹配的特性实例，若无则为 null</returns>
	public static T? GetCachedAttribute<T>(PropertyInfo prop) where T : Attribute
	{
		var attributes = AttributeCache.GetOrAdd(prop, p =>
			p.GetCustomAttributes().ToDictionary(attr => attr.GetType(), attr => attr));

		// 查找第一个继承自 T 的特性
		foreach (var attr in attributes.Values)
		{
			if (typeof(T).IsAssignableFrom(attr.GetType()))
			{
				return (T)attr; // 转换为 T 类型返回
			}
		}
		return null; // 未找到匹配的特性
	}

	/// <summary>
	/// 获取缓存的枚举选项，若无则生成并缓存
	/// </summary>
	public static List<object> GetCachedEnumOptions(Type enumType) =>
		EnumOptionsCache.GetOrAdd(enumType, type =>
		{
			var names = Enum.GetNames(type);
			var values = Enum.GetValues(type);
			var options = new List<object>();

			for (int i = 0; i < names.Length; i++)
			{
				var field = type.GetField(names[i]);
				var displayAttr = field?.GetCustomAttribute<DisplayAttribute>();
				options.Add(new
				{
					Label = displayAttr?.Name ?? names[i],
					Value = values.GetValue(i)
				});
			}

			return options;
		});

	/// <summary>
	/// 获取缓存的类型（根据 FormNameAttribute），若无则查找并缓存（不区分大小写）
	/// </summary>
	public static Type? GetCachedTypeByFormName(string formName, Assembly assembly) =>
		FormNameTypeCache.GetOrAdd((formName, assembly.FullName ?? assembly.GetName().Name ?? string.Empty), _ =>
			FindTypeByFormName(formName, assembly));

	/// <summary>
	/// 在程序集中查找标记了指定 FormNameAttribute 的类型（不区分大小写）
	/// </summary>
	private static Type? FindTypeByFormName(string formName, Assembly assembly) =>
		assembly.GetTypes()
			.Where(t => t.IsClass && !t.IsAbstract)
			.FirstOrDefault(t => string.Equals(t.GetCustomAttribute<FormNameAttribute>()?.Name,
				formName, StringComparison.OrdinalIgnoreCase));

	/// <summary>
	/// 清空所有缓存（可选，用于调试或重置）
	/// </summary>
	public static void ClearCache()
	{
		PropertyCache.Clear();
		AttributeCache.Clear();
		EnumOptionsCache.Clear();
		FormNameTypeCache.Clear();
	}
}
